package org.amse.korovkin.ciphering.model;
import java.io.*;
import java.nio.channels.FileChannel;
import java.util.zip.DataFormatException;

public class Statistic {
    public static final String FILE_STATISTIC = "current_stat.dat";
    
    /**
     * Find Frequency of all Symbols in File with path "inFile".
     * write it in {@code TableOfFrequency}.
     * @param inFile Path of File with text.
     * @return Table with Frequencies of all symbols of text.
     * @throws java.io.IOException if {@code inFile} is incorrect.
     */
    public static TableOfFrequency calcFrequency(String inFile)
            throws IOException, ArrayIndexOutOfBoundsException {
        TableOfFrequency table = new TableOfFrequency();
        int i;
        int fileLength = 0;
        FileReader fReader = new FileReader(inFile);
        while ((i = fReader.read()) != -1) {            
            char ch = (char)i;
            if (ch == '\n' || ch == '\r') {
                continue;
            }
            if (table.contains(ch)) {
                table.incFrequency(ch, 1);
            } else {
                table.addChar(ch);
                table.incFrequency(ch, 1);
            }
            fileLength++;
        }        
        table.divFrequency(fileLength);        
        return table;
    }
    /**
     * Find Bigram Frequency of all Bigrams in File with path "inFile".
     * @param inFile Path of File with text.
     * @return BigramTable with BigramFrequencies of all Bigrams of text.
     * @throws java.io.IOException if {@code inFile} is incorrect.
     */
    public static BigramFrequency calcBigramFrequency(String inFile)
            throws IOException {
        BigramFrequency biTable = new BigramFrequency();
        int y;
        int x;
        int fileLength = 0;
        FileReader fReader = new FileReader(inFile);
        if ((x = fReader.read()) == -1) {
            return biTable;
        }       
        if ((char)x != '\n' && (char)x != '\n' && !biTable.contains((char)x)) {
            biTable.addChar((char) x);
            fileLength++;
        }
        while ((y = fReader.read()) != -1) {            
            if ((char)y == '\n' || (char)y == '\r') {
                continue;
            }
            if (biTable.contains((char)y)) {
                biTable.incFrequency((char)x, (char)y, 1);
            } else {
                biTable.addChar((char) y);
                biTable.incFrequency((char)x, (char)y, 1);
            }            
            fileLength++;
            x = y;
        }       
        biTable.divFrequency(fileLength-1);
        return biTable;
    }
    /**
     * Find Frequency of all symbols and all Bigrams in text with path {@code inFile} and
     * write this to files of Statistic.
     * @see #calcFrequency(String inFile)
     * @see #calcBigramFrequency(String inFile)
     * @param inFile Path of File with text.
     * @throws java.io.IOException if {@code inFile} is incorrect.
     */
    public static void createEtalonStatistic(String inFile)
            throws IOException, DataFormatException, ArrayIndexOutOfBoundsException {
        TableOfFrequency standart = new TableOfFrequency();
        BigramFrequency biStandart = new BigramFrequency();
        try {
            standart = Statistic.calcFrequency(inFile);
            standart.sortLetters();
            if (standart.getNum() < 26) {
                throw new DataFormatException("Statistic is not enough,\n " +
                        "please choose more comprehensive StatisticFile");
            }
            biStandart = Statistic.calcBigramFrequency(inFile);
            biStandart.sortLetters();

            writeStatisticToFile(standart, biStandart);
        } catch (IOException e) {
            throw new IOException("Cann't find StatisticFile. ");
        }
    }
    private static void writeStatisticToFile(TableOfFrequency frec, BigramFrequency bigram)
            throws IOException {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(FILE_STATISTIC));
        frec.writeToFile(dos);
        bigram.writeToFile(dos);
        dos.close();
    }

    /**
     * Get Statistic(Frequency of symbols) from Statistic files.
     * @return Table with Frequencies of symbols.
     */
    public static TableOfFrequency loadEtalonFrequency() 
            throws ArrayIndexOutOfBoundsException, IOException{
        TableOfFrequency standart = new TableOfFrequency();        
        try {
            standart.readFromFile(FILE_STATISTIC);
        }
        catch (IOException e) {
            e.printStackTrace();
            throw new IOException("Statistic Error - can not open " + FILE_STATISTIC + ".\n");
        }
        return standart;
    }

    /**
     * Get Statistic(Frequency of bygrams) from Statistic files.
     * @return Table with Frequencies of Bigrams.
     * @throws java.io.IOException if Statistic file doesn't exist.
     */
    public static BigramFrequency loadEtalonBigram()
    throws IOException {
        BigramFrequency biStandart = new BigramFrequency();
        biStandart.readFromFile(FILE_STATISTIC);
        return biStandart;
    }

    public static void copyStatistic(String statisticPath) {
        FileInputStream src;
        FileOutputStream dest;
        try {
            src = new FileInputStream(statisticPath);
            dest = new FileOutputStream(FILE_STATISTIC);
            FileChannel srcChannel = src.getChannel();
            FileChannel destChannel = dest.getChannel();
            srcChannel.transferTo(0, srcChannel.size(), destChannel);
        } catch (FileNotFoundException ex) {
        } catch (IOException e) {
        }
    }

}
